home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
umddvi
/
dev
/
dmd-sp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-01
|
14KB
|
569 lines
/*
* Support drawing routines for Chris Torek's DVI->ImPress program.
*/
#include <stdio.h>
#include <ctype.h>
#include "types.h"
#include "dmdcodes.h"
/* Put a two-byte (word) value to the Imagen */
#define putword(w) (putchar((w) >> 8), putchar(w))
extern char *malloc();
#define TRUE 1
#define FALSE 0
#define PI 3.14157926536
#define TWOPI (PI*2.0)
#define MAXPOINTS 300 /* Most number of points in a path */
/* Graphics operations */
#define WHITE 0
#define SHADE 3
#define OR 7
#define BLACK 15
extern double cos(), sin(), sqrt();
extern int DPI; /* Resolution of device */
#define PixPerInX DPI
#define PixPerInY DPI
extern int UserMag;
#define fconv(x, f)\
(((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0))
#define conv(x, f)\
((int) ((((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0)) + 0.5))
#define xconv(x) conv(x, PixPerInX)
#define yconv(y) conv(y, PixPerInY)
extern int ImHH; /* Imagen horizontal position */
extern int ImVV; /* Imagen vertical position */
extern int hh; /* current horizontal position, in DEVs */
extern int vv; /* current vertical position, in DEVs */
static int xx[MAXPOINTS], yy[MAXPOINTS], pathlen,
pensize = 1; /* Size we want Imagen to draw at, default 2 pixels */
#define MAXPENSIZE 20 /* Imagen restriction */
static int
family_defined = FALSE, /* Have we chosen family yet? */
texture_defined = FALSE,/* Have we done a set_texture yet? */
whiten_next = FALSE, /* Should next object be whitened? */
blacken_next = FALSE, /* Should next object be blackened? */
shade_next = FALSE; /* Should next object be shaded? */
/* Predefined shading (texture) glyph */
/* First, define size of glyph */
#define THEIGHT 32 /* bits high */
#define TWIDTH 4 /* bytes wide */
/* Next, declare the bit map for the glyph */
static char stexture[THEIGHT][TWIDTH]={
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
/*
* Copy a default texture into the stexture array
*/
static void glyph_init()
{
static char btexture[THEIGHT][TWIDTH]={
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
{0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
int i;
for (i=0; i<THEIGHT; i++)
bcopy(btexture[i],stexture[i],TWIDTH);
}
#define push_location()
#define pop_location()
#ifdef notdef
/*
* Push the state of the Imagen and set up a new virtual coord system
*/
static void push_location()
{
putchar(imP_Push);
putchar(imP_SetHVSystem);
putchar(0140);
}
/*
* Create the pushed virtual page, and pop the state of the printer
*/
static void pop_location()
{
putchar(imP_Pop);
}
#endif
/*
* Set the pen size
* Called as \special{pn size}
* eg: \special{pn 8}
* The size is the number of milli-inches for the diameter of the pen.
* This routine converts that value to device-dependent pixels, and makes
* sure that the resulting value is within legal bounds.
*/
static void im_pensize(cp)
char *cp;
{
int size;
if (sscanf(cp, " %d ", &size) != 1) return;
pensize = yconv(size);
if (pensize < 1) pensize = 1;
else if (pensize > MAXPENSIZE) pensize = MAXPENSIZE;
}
/*
* Make sure the pen size is set. Since we push and pop the state,
* this has to be sent for each different object (I think).
*/
static void set_pen_size()
{
putchar(DMD_PENSIZE);
putchar(pensize);
}
/*
* Actually apply the attributes (shade, whiten, or blacken) to the currently
* defined path/figure.
*/
static void do_attributes()
{
static int family; /* Family of downloaded texture glyph */
static int member; /* Member of family */
int i,j; /* Loop through glyph array */
if (shade_next) {
shade_next = FALSE;
#ifdef notdef
if (!family_defined) {
family_defined = TRUE;
family = fnum++;
member = -1;
}
if (!texture_defined) {
texture_defined = TRUE;
member++;
putchar(imP_DefGlyph);
putchar((family & 0x7e) >> 1);
putchar((family & 0x01) << 7 | (member & 0x7f));
/*putword(0); */ /* Advance width */
putword(32);
putword(TWIDTH*8); /* pixel width (8 x number of bytes) */
/*putword(0); */ /* left offset */
putword(32);
putword(THEIGHT); /* and height of glyph */
/*putword(0); */ /* top offset */
putword(32);
for (i=0; i<THEIGHT; i++)/* Do rows */
for (j=0; j<TWIDTH; j++) putchar(stexture[i][j]);
}
putchar(imP_SetTexture);
putchar((family & 0x7e) >> 1);
putchar((family & 0x01) << 7 | (member & 0x7f));
#endif
putchar(DMD_FILLPATH);
putchar(SHADE);
glyph_init(); /* reinitialize the array */
}
else if (whiten_next) {
whiten_next = FALSE;
putchar(DMD_FILLPATH);
putchar(WHITE);
}
else if (blacken_next) {
blacken_next = FALSE;
putchar(DMD_FILLPATH);
putchar(BLACK);
}
}
/*
* Flush the path that we've built up with im_drawto()
* Called as \special{fp}
*/
static void im_flushpath()
{
register int i;
push_location();
if (pathlen <= 0) return;
set_pen_size();
putchar(DMD_SEGMENT);
putword(pathlen);
for (i=1; i<=pathlen; i++) {
putword(xx[i]);
putword(yy[i]);
}
pathlen = 0;
putchar(DMD_DRAWPATH);
putchar(BLACK);
do_attributes();
pop_location();
}
/* Helper routine for dashed_line() */
static void connect(x0, y0, x1, y1)
int x0, y0, x1, y1;
{
set_pen_size();
putchar(DMD_SEGMENT);
putword(2); /* Path length */
putword(x0); putword(y0);/* The path */
putword(x1); putword(y1);
putchar(DMD_DRAWPATH);
putchar(BLACK);
}
/* Another helper. Draw a dot at the indicated point */
static void dot_at(x, y)
int x,y;
{
set_pen_size();
putchar(DMD_SEGMENT);
putword(1); /* Path length */
putword(x); putword(y); /* The path */
putchar(DMD_DRAWPATH);
putchar(BLACK);
}
/*
* Draw a dashed or dotted line between the first pair of points in the array
* Called as \special{da <inchesperdash>} (dashed line)
* or \special{dt <inchesperdot>} (dotted line)
* eg: \special{da 0.05}
*/
static void dashed_line(cp, dotted)
char *cp;
int dotted; /* boolean */
{
int i, numdots, x0, y0, x1, y1;
double cx0, cy0, cx1, cy1;
double d, spacesize, a, b, dx, dy, pixperdash;
float inchesperdash;
if (sscanf(cp, " %f ", &inchesperdash) != 1) return;
if (pathlen <= 1) return;
pixperdash = inchesperdash * ((float) PixPerInY);
if (pixperdash < 2.)
pixperdash = 2.;
x0 = xx[1]; x1 = xx[2];
y0 = yy[1]; y1 = yy[2];
dx = x1 - x0;
dy = y1 - y0;
push_location();
if (dotted) {
numdots = sqrt(dx*dx + dy*dy) / pixperdash + 0.5;
if (numdots > 0)
for (i = 0; i <= numdots; i++) {
a = (float) i / (float) numdots;
cx0 = ((float) x0) + (a*dx) + 0.5;
cy0 = ((float) y0) + (a*dy) + 0.5;
dot_at((int) cx0, (int) cy0);
}
}
else {
d = sqrt(dx*dx + dy*dy);
if (d <= 2 * pixperdash) {
connect(x0, y0, x1, y1);
pathlen = 0;
pop_location();
return;
}
numdots = d / (2 * pixperdash) + 1;
spacesize = (d - numdots * pixperdash) / (numdots - 1);
for (i=0; i<numdots-1; i++) {
a = i * (pixperdash + spacesize) / d;
b = a + pixperdash / d;
cx0 = ((float) x0) + (a*dx) + 0.5;
cy0 = ((float) y0) + (a*dy) + 0.5;
cx1 = ((float) x0) + (b*dx) + 0.5;
cy1 = ((float) y0) + (b*dy) + 0.5;
connect((int) cx0, (int) cy0, (int) cx1, (int) cy1);
b += spacesize / d;
}
cx0 = ((float) x0) + (b*dx) + 0.5;
cy0 = ((float) y0) + (b*dy) + 0.5;
connect((int) cx0, (int) cy0, x1, y1);
}
pathlen = 0;
pop_location();
}
/*
* Virtually draw to a given x,y position on the virtual page.
* X and Y are expressed in thousandths of an inch, and this
* routine converts them to pixels.
*
* Called as \special{pa <x> <y>}
* eg: \special{pa 0 1200}
*/
static void im_drawto(cp)
char *cp;
{
int x,y;
if (sscanf(cp, " %d %d ", &x, &y) != 2) return;
if (++pathlen >= MAXPOINTS)
error(1, 0, "Too many points specified");
xx[pathlen] = xconv(x) + ImHH;
yy[pathlen] = yconv(y) + ImVV;
}
/* Same routine as above, but it uses the special graphics primitives */
static void im_arc(cp)
char *cp;
{
int xc, yc, xrad, yrad;
float start_angle, end_angle, fxrad, fyrad;
int xp, yp;
if (sscanf(cp, " %d %d %d %d %f %f ", &xc, &yc, &xrad, &yrad, &start_angle,
&end_angle) != 6) return;
push_location();
set_pen_size();
xc = xconv(xc) + ImHH;
yc = yconv(yc) + ImVV;
{
double temp;
temp = start_angle;
start_angle = end_angle;
end_angle = temp;
}
if (xrad >= yrad-1 && xrad <= yrad+1) { /* Circle or arc */
putchar(DMD_CIRCLE);
putword(xc); putword(yc);
/* starting point */
fyrad = fconv(yrad, PixPerInY);
xp = fyrad * cos(start_angle) + xc + .5;
yp = fyrad * sin(start_angle) + yc + .5;
putword(xp); putword(yp);
/* finishing point */
xp = fyrad * cos(end_angle) + xc + .5;
yp = fyrad * sin(end_angle) + yc + .5;
putword(xp); putword(yp);
}
else { /* Ellipse */
putchar(DMD_ELLIPSE);
putword(xc); putword(yc);
/* starting point */
fxrad = fconv(xrad, PixPerInX);
fyrad = fconv(yrad, PixPerInY);
xp = fxrad * cos(start_angle) + xc + .5;
yp = fyrad * sin(start_angle) + yc + .5;
putword(xp); putword(yp);
/* finishing point */
xp = fxrad * cos(end_angle) + xc + .5;
yp = fyrad * sin(end_angle) + yc + .5;
putword(xp); putword(yp);
putword(xconv(xrad));
putword(yconv(yrad));
}
putchar(DMD_DRAWPATH);
putchar(BLACK);
do_attributes();
pop_location();
}
/*
* Create a spline through the points in the array.
* Called like flush path (fp) command, after points
* have been defined via pa command(s).
*
* eg: \special{sp}
*/
static void flush_spline()
{
register int i;
push_location();
if (pathlen <= 0) return;
set_pen_size();
putchar(DMD_SPLINE);
putword(pathlen);
for (i=1; i<=pathlen; i++) {
putword(xx[i]);
putword(yy[i]);
}
pathlen = 0;
putchar(DMD_DRAWPATH);
putchar(BLACK);
do_attributes();
pop_location();
}
/*
* Whiten the interior of the next figure (path). Command is:
* \special{wh}
*/
static void im_whiten()
{
whiten_next = TRUE;
}
/*
* Blacken the interior of the next figure (path). Command is:
* \special{bk}
*/
static void im_blacken()
{
blacken_next = TRUE;
}
/*
* Shade the interior of the next figure (path) with the predefined
* texture. Command is:
* \special{sh}
*/
static void im_shade()
{
shade_next = TRUE;
}
/*
* Define the texture array. Command is:
* \special{tx 32bits 32bits ....}
*/
static void im_texture(pcount,bitpattern)
int pcount, bitpattern[32];
{
int i,j,k;
unsigned long ul_one;
#ifdef notdef
#ifdef DEBUG
if (sizeof ul_one != TWIDTH)
error(1, 0, "pointer/size mismatch");
#endif
j = 0;
for (k=0; k < THEIGHT/pcount; k++) {
for (i=0; i<pcount; i++) {
ul_one = htonl((unsigned long) bitpattern[i]);
bcopy((char *) &ul_one, stexture[j++], TWIDTH);
}
}
texture_defined = FALSE;
#endif
}
/*
* This routine takes the string argument for a tx command and
* parses out the separate bitpatterns to call im_texture with.
* Written by Tinh Tang
*/
static void do_texture(t)
char *t;
{
int bitpattern[32];
int pcount = 0;
while (isspace (*t)) t++;
while (*t) {
if (sscanf(t, "%x", &bitpattern[pcount++]) != 1) {
error(0, 0, "malformed tx command");
return;
}
while (*t && !isspace(*t)) t++;/* Skip to space */
while (*t && isspace(*t)) t++;/* Skip to nonspace */
}
if (pcount != 4 && pcount != 8 && pcount != 16 && pcount != 32) {
error(0, 0, "malformed tx command");
return;
}
im_texture(pcount, bitpattern);
}
#define COMLEN 3 /* Length of a tpic command plus one */
DoSpecial(k)
i32 k;
{
char *spstring, *cp, command[COMLEN];
register int len;
spstring = malloc((unsigned) (k+1));
if (spstring == NULL) error(2, 0, "Out of memory");
len = 0;
while (k--) spstring[len++] = GetByte(stdin);
spstring[len] = '\0';
cp = spstring;
while (isspace(*cp)) ++cp;
len = 0;
while (!isspace(*cp) && *cp && len < COMLEN-1) command[len++] = *cp++;
command[len] = '\0';
if (ImHH != hh || ImVV != vv)
ImSetPosition(hh, vv);
if (strcmp(command, "pn") == 0) im_pensize(cp);
else if (strcmp(command, "fp") == 0) im_flushpath();
else if (strcmp(command, "da") == 0) dashed_line(cp, 0);
else if (strcmp(command, "dt") == 0) dashed_line(cp, 1);
else if (strcmp(command, "pa") == 0) im_drawto(cp);
else if (strcmp(command, "ar") == 0) im_arc(cp);
else if (strcmp(command, "sp") == 0) flush_spline();
else if (strcmp(command, "sh") == 0) im_shade();
else if (strcmp(command, "wh") == 0) im_whiten();
else if (strcmp(command, "bk") == 0) im_blacken();
else if (strcmp(command, "tx") == 0) im_texture(cp);
else error(0, 0, "warning: ignoring \\special");
free(spstring);
}